﻿namespace MEF_Test.Formats.Avi
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.InteropServices;

    using MediaInfoLib;

    using MEF_Test.Contracts;
    using MEF_Test.Subtitles;

    public class AviMediaHandler : IVideoMediaHandler
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AviMediaHandler"/> class.
        /// </summary>
        /// <param name="fileHandler">The file handler.</param>
        public AviMediaHandler(IFileHandler fileHandler)
        {
            if (fileHandler == null)
            {
                throw new ArgumentNullException("fileHandler");
            }
            _mediaInfo = AnalyseMediaInfoStream(fileHandler.GetStream());  
          
            Subtitles = new List<ISubtitleHandler>();
        }

        #region IMediaHandler Members
     
        private TimeSpan _duration = TimeSpan.Zero;

        private readonly MediaInfo _mediaInfo;

        /// <summary>
        /// Gets the duration.
        /// </summary>
        /// <value>The duration.</value>
        public TimeSpan Duration
        {
            get 
            {
                if (_duration == TimeSpan.Zero)
                {                    
                    var v = _mediaInfo.Get(StreamKind.Video, 0, "Duration");
                    _duration = TimeSpan.FromMilliseconds(int.Parse(v));
                    _duration = _duration.Subtract(TimeSpan.FromMilliseconds(_duration.Milliseconds));                   
                }

                return _duration; 
            }
        }
       
        /// <summary>
        /// Gets or sets the subtitles.
        /// </summary>
        /// <value>The subtitles.</value>
        public List<ISubtitleHandler> Subtitles { get; set; }

        /// <summary>
        /// Analyses the media info stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns></returns>
        private MediaInfo AnalyseMediaInfoStream(Stream stream)
        {            
            var mi = new MediaInfo();
            mi.Open_Buffer_Init(stream.Length, stream.Position);           
            var buffer = new byte[1024];
            GCHandle bufferHandle;
            int retval;
            do
            {
                stream.Read(buffer, 0, buffer.Length);

                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject();
                retval = mi.Open_Buffer_Continue(bufferPtr, (IntPtr)buffer.LongLength);
            }
            while ((retval & 1) != 1);
            mi.Open_Buffer_Finalize();
            return mi;
        }

        /// <summary>
        /// Gets or sets the name of the file.
        /// </summary>
        /// <value>The name of the file.</value>
        public string FileName { get; set; }

        #endregion
    }
}
